package cn.keepme.dao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.beanutils.BeanUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Example;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;

import cn.keepme.common.utils.Page;
import cn.keepme.common.utils.PageUtil;


@Component
public abstract class BaseDAO<T,PK extends Serializable> extends HibernateDaoSupport {
	
	@Resource
	public void setSessionFactoryOverride(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
	
	public abstract Class<T> getEntityClass();
	
	public void delete(T t) {
		getSession().delete(t);
		
	}

	public List<T> findAll() {
		Criteria criteria=getSession().createCriteria(getEntityClass());
		return criteria.list();
	}

	public List<T> findByExample(T t) {
		List results = getSession().createCriteria(getEntityClass()).add(Example.create(t)).list();
		return results;
	}

	public T findById(PK id) {
		T t=(T)getSession().get(getEntityClass(), id);
		return t;
	}

	public void merge(T t) {
		getSession().merge(t);
	}

	public void save(T t) {
		getSession().save(t);
	}

	public void update(T t) {
		getSession().update(t);
	}
	
	
	/**
	 * @param hql 查询语句
	 * @param countHql 查询总记录数语句
	 * @param pageNo 页号
	 * @param pageSize 每页显示记录数
	 * @return
	 */
	public Page queryPageByHql(String hql,String countHql,int pageNo,int pageSize,List<Object> params){
		int maxPageSize=Integer.parseInt(this.queryObjectByHql(countHql, params).toString());
		Query query=this.getSession().createQuery(hql);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		query.setFirstResult((pageNo-1)*pageSize);
		query.setMaxResults(pageSize);
		List<Object> list=query.list();
		Page page=PageUtil.doPage(pageNo, pageSize, maxPageSize, list);
		return page;
	}
	
	public List queryListByHql(String hql,List<Object> params){
		Query query=this.getSession().createQuery(hql);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		List<Object> list=query.list();
		return list;
	}
	
	public List queryListByHql(String hql,List<Object> params,int beginIndex,int pageSize){
		Query query=this.getSession().createQuery(hql);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		query.setFirstResult(beginIndex);
		query.setMaxResults(pageSize);
		List<Object> list=query.list();
		return list;
	}
	
	
	public Page queryPageBySql(String sql,String countSql,int pageNo,int pageSize,List<Object> params){
		int maxPageSize=Integer.parseInt(this.queryObjectBySql(countSql, params).toString());
		Query query=this.getSession().createSQLQuery(sql);
		query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		query.setFirstResult((pageNo-1)*pageSize);
		query.setMaxResults(pageSize);
		List<Object> list=query.list();
		Page page=PageUtil.doPage(pageNo, pageSize, maxPageSize, list);
		return page;
	}
	
	public List queryListBySql(String sql,Class clazz,List<Object> params) throws InstantiationException, IllegalAccessException, InvocationTargetException{
		List rlist=new ArrayList();
		Query query=this.getSession().createSQLQuery(sql);
		query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		List<Object> list=query.list();
		for(Object map : list){
			Object obj=clazz.newInstance();
			BeanUtils.populate(obj,(Map)map);
			rlist.add(obj);
		}
		return rlist;
	}
	
	public List<Object> queryListBySql(String sql,List<Object> params){
		Query query=this.getSession().createSQLQuery(sql);
		query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		List<Object> list=query.list();
		return list;
	}
	
	public Object queryObjectBySql(String sql,List<Object> params){
		Query query=this.getSession().createSQLQuery(sql);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		return query.uniqueResult();
	}
	
	public Object queryObjectByHql(String hql,List<Object> params){
		Query query=this.getSession().createQuery(hql);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		return query.uniqueResult();
	}
	
	public int executeHql(String hql,List<Object> params){
		Query query=this.getSession().createQuery(hql);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		return query.executeUpdate();
	}
	
	public int executeSql(String sql,List<Object> params){
		Query query=this.getSession().createSQLQuery(sql);
		if(params!=null){
			for(int i=0;i<params.size();i++){
				query.setParameter(i, params.get(i));
			}
		}
		return query.executeUpdate();
	}
}

